﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Threading.Tasks;

namespace ImageCompression
{
    /// <summary>
    /// 图片压缩类
    /// Bao
    /// 联系：gsbhz@qq.com
    /// </summary>
    public class ImgCompression
    {
        #region Fields
        //Thread td;//创建线程
        Image ig = null;

        private List<ImgInfoEntity> _imgList;
        public string _savePath;
        public int _rate;

        public System.Windows.Forms.ProgressBar ProgressBar { private get; set; }
        public System.Windows.Forms.Label ProgressText { private get; set; }
        public System.Windows.Forms.DataGridView Dgv { private get; set; }

        int _total, _index;
        #endregion

        #region constructor
        /// <summary>
        /// 图片压缩
        /// </summary>
        /// <param name="imgList">要压缩的图片列表</param>
        /// <param name="rate">缩放比率</param>
        /// <param name="savePath">保存路径</param>
        public ImgCompression(List<ImgInfoEntity> imgList, int rate, string savePath) 
        {
            this._imgList = imgList;
            this._rate = rate;
            this._savePath = savePath;

            this._total = imgList.Count;
            this._index = 0;
        }
        #endregion

        #region 入口方法
        public void Start()
        {
            string msg = "";
            if (this._imgList == null || this._imgList.Count == 0)
                msg = "请选择要压缩的图片";
            else if (this._rate < 0 || this._rate > 100)
                msg = "压缩比率要介于0~100之间";
            else if (string.IsNullOrEmpty(this._savePath))
                msg = "请选择保存路径";
            if (!string.IsNullOrEmpty(msg))
            {
                System.Windows.Forms.MessageBox.Show(msg, "错误", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
                return;
            }

            //td = new Thread(new ThreadStart(this.Compression));//创建线程
            //td.Start();//开始线程

            this.ProgressBar.Minimum = 0;
            this.ProgressBar.Maximum = this._total;
            this.ProgressBar.Value = 0;

            Compression();
        }
        #endregion

        #region 压缩
        private async void Compression()
        {
            foreach (ImgInfoEntity img in _imgList)
            {
                

                //从指定的文件中创建Image对象
                ig = Image.FromFile(img.FullPath);

                //调用无损压缩方法
                var result = GetPicThumbnail(img.FullPath, Convert.ToInt32(ig.Width * (this._rate / 100f)), Convert.ToInt32(ig.Height * (this._rate / 100f)));
                var r = await result;
                if (r.Success)
                {
                    this._index++;
                    this.ProgressBar.Value = this._index;
                    this.ProgressText.Text = this._index + "/" + this._total;
                    this.Dgv.Rows[this._index - 1].Cells["NewBytes"].Value = r.NewBytes;
                    this.Dgv.Rows[this._index - 1].Cells["NewSize"].Value = r.NewSize;
                }

                ig.Dispose();//释放资源
            }
        }
        #endregion

        #region 无损压缩图片
        /// <summary>
        /// 无损压缩图片
        /// </summary>
        /// <param name="sFile">图片的原始路径</param>
        /// <param name="dHeight">缩放后图片的高度</param>
        /// <param name="dWidth">缩放后图片的宽带</param>
        /// <returns></returns>
        private async Task<CompressionResult> GetPicThumbnail(string sFile, int dHeight, int dWidth)
        {
            return await Task.Run(() =>
            {
                Image iSource = Image.FromFile(sFile);//从指定的文件创建Image
                ImageFormat tFormat = iSource.RawFormat;//指定文件的格式并获取
                int sW = 0, sH = 0;//记录宽度和高度
                Size tem_size = new Size(iSource.Width, iSource.Height);//实例化size。知矩形的高度和宽度
                if (tem_size.Height > dHeight || tem_size.Width > dWidth)//判断原图大小是否大于指定大小
                {
                    //if ((tem_size.Width * dHeight) > (tem_size.Height * dWidth))
                    //{
                    //    sW = dWidth;
                    //    sH = (dWidth * tem_size.Height) / tem_size.Width;
                    //}
                    //else
                    //{
                    //    sH = dHeight;
                    //    sW = (tem_size.Width * dHeight) / tem_size.Height;
                    //}
                    sW = dWidth;
                    sH = dHeight;
                }
                else//如果原图大小小于指定的大小
                {
                    sW = tem_size.Width;//原图宽度等于指定宽度
                    sH = tem_size.Height;//原图高度等于指定高度
                }
                Bitmap oB = new Bitmap(dWidth, dHeight);//实例化
                Graphics g = Graphics.FromImage(oB);//从指定的Image中创建Graphics
                g.Clear(Color.Transparent);//设置画布背景颜色
                g.CompositingQuality = CompositingQuality.HighQuality;//合成图像的呈现质量
                g.SmoothingMode = SmoothingMode.HighQuality;//呈现质量
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;//插补模式
                //开始重新绘制图像
                g.DrawImage(iSource, new Rectangle((dWidth - sW) / 2, (dHeight - sH) / 2, sW, sH), 0, 0, iSource.Width, iSource.Height, GraphicsUnit.Pixel);
                g.Dispose();//释放资源
                //保存图片时，设置压缩质量
                EncoderParameters ep = new EncoderParameters();//用于向图像编码器传递值
                long[] qy = new long[1];
                qy[0] = 100;
                EncoderParameter eParm = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);
                ep.Param[0] = eParm;
                try
                {
                    //获得包含有关内置图像编码器的信息的ImageCodeInfo对象
                    ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageDecoders();
                    ImageCodecInfo jpegICIinfo = null;
                    for (int x = 0; x < arrayICI.Length; x++)
                    {
                        if (arrayICI[x].FormatDescription.Equals("JPEG"))
                        {
                            jpegICIinfo = arrayICI[x];
                            break;
                        }
                    }

                    string fileName = Path.GetFileName(sFile);
                    fileName = Path.Combine(this._savePath, fileName);
                    // 检查图片是否存在，如果存在，则重命名。。
                    if (File.Exists(fileName))
                    {
                        string ext = Path.GetExtension(fileName);
                        fileName = fileName.Replace(ext, "-1" + ext);
                    }
                    if (jpegICIinfo != null)
                    {
                        oB.Save(fileName, jpegICIinfo, ep);
                    }
                    else
                    {
                        oB.Save(fileName, tFormat);// 已指定格式保存到指定文件
                    }

                    string newBytes;
                    using (FileStream fs = File.Open(fileName, FileMode.Open, FileAccess.Read))
                    {
                        newBytes = Common.ByteConversion(fs.Length);
                        fs.Close();
                        fs.Dispose();
                    }
                    
                    return new CompressionResult() { Success = true, NewBytes = newBytes, NewSize = sW + "×" + sH };
                }
                catch
                {
                    return new CompressionResult() { Success = false};
                }
                finally
                {
                    iSource.Dispose();//释放资源
                    oB.Dispose();
                }
            });
        }
        #endregion
    }

    #region 生成图片结果
    class CompressionResult
    {
        public bool Success { get; set; }
        public string NewBytes { get; set; }
        public string NewSize { get; set; }
    }
    #endregion
}
